﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IRProject.Model
{
    class QueryToTreeHandler
    {
        enum Operation
        {
            And,
            Or,
            LBrace,
            RBrace
        }

        IFtidfAlgorithmProvider _tfidfServes;
        List<Node> _leafNode = new List<Node>();
        List<Operation> _opList = new List<Operation>();
        List<Node> _opNode = new List<Node>();
        String OriginalQuery;

        public QueryToTreeHandler(IFtidfAlgorithmProvider tfidf) 
        {
            this._tfidfServes = tfidf;
        }

        public List<ResultData> GetResultList(String query) 
        {
            OriginalQuery = query;
            Node treeRoot = QueryToTree(query);

            return treeRoot.GetResult();
        }

        Node QueryToTree(String query)
        {
            query = StandardizeQuery(query);
            String[] tremPart = query.Split('(',')','|','&');
            for (int i = 0; i < tremPart.Length; i++) 
            {
                if (tremPart[i].Length > 0) 
                {
                    LeafNode leafNode = new LeafNode(_tfidfServes, tremPart[i]);
                    _leafNode.Add(leafNode);
                }
            }

            foreach (LeafNode node1 in _leafNode)
            {
                node1.Calculate(_tfidfServes.Documents);
            }

            Char[] c = query.ToCharArray();
            Node node;
            for (int i = 0; i < c.Length; i++) 
            {
                switch (c[i]) 
                {
                    case '(':
                        _opList.Add(Operation.LBrace);
                        break;
                    case ')':
                        _opList.Add(Operation.RBrace);
                        break;
                    case '&':
                        node = new AndNode();
                        _opNode.Add(node);
                        _opList.Add(Operation.And);
                        break;
                    case '|':
                        node = new OrNode();
                        _opNode.Add(node);
                        _opList.Add(Operation.Or);
                        break;
                }
            }

            while (_opList.Contains(Operation.LBrace)) 
            {
                int lastLPos = 0, tempi = 0, firstRPos = 0, opCount = 0;
                for (int i = 0; i < _opList.Count; i++) 
                {
                    if (_opList[i] == Operation.LBrace)
                    {
                        lastLPos = i;
                    }
                }

                for (int i = lastLPos; i < _opList.Count; i++)
                {
                    if (_opList[i] == Operation.RBrace)
                    {
                        firstRPos = i;
                        break;
                    }
                }

                for (int i = 0; i < lastLPos; i++) 
                {
                    if (_opList[i] == Operation.And || _opList[i] == Operation.Or)
                    {
                        tempi++; //2
                    }
                }

                for (int i = lastLPos; i < firstRPos; i++)     //括號內有幾個OP
                {
                    if (_opList[i] == Operation.And || _opList[i] == Operation.Or)
                    {
                        opCount++;
                    }
                }

                for (int i = 0; i < opCount; i++)
                {
                    _opNode[tempi].Add(_leafNode[tempi]);
                    _opNode[tempi].Add(_leafNode[tempi + 1]);

                    _leafNode.RemoveAt(tempi + 1);
                    _leafNode.RemoveAt(tempi);
                    _leafNode.Insert(tempi, _opNode[tempi]);
                    _opNode.RemoveAt(tempi);
                }

                for (int i = firstRPos; i >= lastLPos; i--)     //括號內有幾個OP
                {
                    _opList.RemoveAt(i);

                }
                //if (tempi == 2) { }
            }

            while (_opNode.Count > 0) 
            {
                _opNode[0].Add(_leafNode[0]);
                _opNode[0].Add(_leafNode[1]);
                _leafNode.RemoveAt(1);
                _leafNode.RemoveAt(0);
                _leafNode.Insert(0, _opNode[0]);
                _opNode.RemoveAt(0);
            }

            return _leafNode[0];
        }

        String StandardizeQuery(String query) 
        {
            query = query.Replace(" ", "");
            query = query.Replace("&&", "&");
            query = query.Replace("||", "|");
            return query;
        }
    }
}
